package ithink.link.service;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;

/**
 * Created by zaqb on 17-10-26.
 */
public class PortMappingHelper {
    private static boolean inited = false;
    private static ClientBootstrap bootstrap;
    private static Map<Channel, IListener> listenerMap = new HashMap<>();
    static {
        init();
    }

    private static synchronized void init() {
        if(inited) {
           return;
        }
        bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));
        bootstrap.setPipelineFactory( () -> Channels.pipeline(new ClientHandler()) );
        bootstrap.setOption("allIdleTime","5");
    }

    public static void connect(String ip, int port, IListener listener) {

        ChannelFuture f = bootstrap.connect(new InetSocketAddress(
                ip, port));
        listenerMap.put(f.getChannel(), listener);
    }
    private static class ClientHandler extends SimpleChannelHandler {

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
            IListener listener = listenerMap.get(ctx.getChannel());
            if(listener != null) {
                listener.onFailed();
                listenerMap.remove(ctx.getChannel());
            }
        }

        @Override
        public void channelConnected(ChannelHandlerContext ctx,
                                     ChannelStateEvent e) {
            IListener listener = listenerMap.get(ctx.getChannel());
            if(listener != null) {
                listener.onSuccess();
                listenerMap.remove(ctx.getChannel());
            }
        }
    }

    public static abstract class IListener{
        private String id;
        IListener(String id) {
            this.id = id;
        }

        public String getId() {
            return id;
        }

        public abstract void onSuccess();
        public abstract void onFailed();
    }

    public static void main(String[] args) throws InterruptedException {
        PortMappingHelper.connect( "118.0.55.66", 80, new IListener("za") {
            @Override
            public void onSuccess() {
                System.out.println(this.getId() + "success");
            }

            @Override
            public void onFailed() {
                System.out.println(this.getId() + "onFailed");
            }
        } );
     //   PortMappingHelper.connect( "127.0.0.1", 8000 );
        PortMappingHelper.connect( "61.135.169.125", 80, new IListener("aa") {
            @Override
            public void onSuccess() {
                System.out.println(this.getId() + "success");
            }

            @Override
            public void onFailed() {
                System.out.println(this.getId() + "onFailed");
            }
        } );
        Thread.sleep( 10000*1000 );
    }
}

